package com.xuecheng.producer;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author: gongfy
 * @create: 2020/7/14 17:47
 * @Params:
 * @Description: 发布订阅模式生产者
 */
public class Producer02_publish {

    //定义两个队列和一个交换机
    private static final String QUEUE_INFORM_EMAIL = "queue_inform_email"; //电子邮件队列
    private static final String QUEUE_INFORM_SMS = "queue_inform_sms"; // 手机短息队列
    private static final String EXCHANGE_FANOUT_INFORM="exchange_fanout_inform"; //交换机

    public static void main(String[] args){
        Connection connection = null;
        Channel channel = null;
        try {
            // 通过连接工厂创建新的连接和MQ建立连接
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            factory.setPort(5672);  //  注意不是：http://localhost:15672 web管理端端口  通信端口是：5672
            factory.setUsername("guest");
            factory.setPassword("guest");
            factory.setVirtualHost("/");//rabbitmq默认虚拟机名称为“/”，一个mq服务可以设置多个虚拟机，每一个相当于一个独立的mq服务器
            //1.创建与RabbitMQ服务的TCP连接
            connection = factory.newConnection();
            //2.创建与Exchange的会话通道，每个连接可以创建多个通道，每个通道代表一个会话任务
            channel = connection.createChannel();
            /*  声明一个交换机  String exchange, BuiltinExchangeType type
             * 参数明细:
             * 1.exchange 交换机名称
             * 2.type 交换机类型
             *   fanout:对应的是发布订阅模式 publish/subscribe
             *   direct:对应的是Routing路由模式
             *   topic:对应的是Topic模式
             *   hearders:对应的是headders模式
             * */
            channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);
            /**  目的：需要给队列发送消息
             * 3.声明队列：如果Rabbit中没有此队列将自动创建  queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
             * queue:队列名称
             * durable:是否持久化，如果持久化重启后队列还在
             * exclusive:队列是否独占此连接  队列只允许在该连接中访问，如果连接关闭则自动删除。设置true可用于临时队列的创建
             * autoDelete:队列不再使用时是否自动删除此队列， 如果将此参数和exclusive设置为true就可以实现临时队列（不用了就自动删除）
             * arguments:队列参数  可以设置一些扩展参数，比如，可设置存活时间
             */
            channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);
            channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);
            /* 队列交换机进行绑定  String queue, String exchange, String routingKey
            * 参数明细：
            *   1、queue 队列名称
            *   2、exchange 交换机名称
            *   3、routingKey 路由key  作用：根据key名称将消息转发到指定的队列 在发布订阅模式为空串
            * */
            channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_FANOUT_INFORM,""); // todo 参数传反报错
            channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_FANOUT_INFORM,"");
            
            /**
             * 4.消息发布方法   basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
             * exchange：Exchange的名称，如果没有指定，则使用Default Exchange
             * routingKey: 消息的路由Key，交换机根据路由key将消息转发到指定的队列，如果使用默认交换机，routingKey设置为队列的名称
             * props:消息包含的属性 ，属性一般不用可以放在消息体中
             * body：消息体
             */
            for (int i = 0; i < 5; i++) { // 一次发多个消息
                String message = "Send Inform Message To User！！！" + System.currentTimeMillis();
                channel.basicPublish(EXCHANGE_FANOUT_INFORM, "", null, message.getBytes());
                System.out.println("Send Message To MQ:'" + message + "'");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(channel!=null){
                try {
                    channel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
